package storage.record;

/**
 * @author nilei
 */

import static storage.sql.Types.INTEGER;
import static storage.sql.Types.VARCHAR;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import compiler.absyn.ForeignKey;
import compiler.absyn.Key;
import compiler.absyn.ReferenceKey;
import compiler.absyn.Term;
import compiler.absyn.TypeDef;


public class Schema {
	private Map<String, FieldInfo> info = new HashMap<String, FieldInfo>();
	public static int FALSE = 0;
	public static int TRUE = 1;

	public Schema() {
	}

	public void addField(String fldname, TypeDef td, Key key, ForeignKey fk,
			Term tm) {
		addField(fldname, td.type, td.length, key.prkey, key.notnull,
				fk.tblname == null ? FALSE : TRUE, tm == null ? FALSE : TRUE,
				fk.tblname == null ? null : fk.tblname,
				fk.fldname == null ? null : fk.fldname, tm == null ? null : tm
						.toString(), FALSE, null, null);
	}

	public void addField(String fldname, int type, int length, int iskey,
			int notnull, int fkey, int ischeck, String fkeytblname,
			String fkeyfldname, String termstring, int ir, String rb, String rf) {
		info.put(fldname, new FieldInfo(type, length, iskey, notnull, fkey,
				ischeck, fkeytblname, fkeyfldname, termstring, ir, rb, rf));
	}

	public void addField(String fldname, int type, int length) {
		info.put(fldname, new FieldInfo(type, length, FALSE, FALSE, FALSE,
				FALSE, null, null, null,FALSE, null, null));
	}

	public void addIntField(String fldname) {
		addField(fldname, INTEGER, 0);
	}

	public void addStringField(String fldname, int length) {
		addField(fldname, VARCHAR, length);
	}

	public void addDateField(String fldname) {
		addStringField(fldname, 10);
	}

	public void addTimeField(String fldname) {
		addStringField(fldname, 8);
	}

	public void add(String fldname, Schema sch) {
		int type = sch.type(fldname);
		int length = sch.length(fldname);
		addField(fldname, type, length);
	}

	public void addAll(Schema sch) {
		info.putAll(sch.info);
	}

	public Collection<String> fields() {
		return info.keySet();
	}

	public boolean hasField(String fldname) {
		return fields().contains(fldname);
	}

	public int type(String fldname) {
		return info.get(fldname).type;
	}

	public int length(String fldname) {
		return info.get(fldname).length;
	}

	public int iskey(String fldname) {
//		System.out.println("info:"+info.keySet());
//		System.out.println("fldname:"+fldname);
		return info.get(fldname).iskey;
	}

	public int notnull(String fldname) {
		return info.get(fldname).notnull;
	}

	public int fkey(String fldname) {
		return info.get(fldname).fkey;
	}

	//	
	// public boolean isfkey(String fldname){
	// return info.get(fldname).fkey == TRUE;
	// }

	public int ischeck(String fldname) {
		return info.get(fldname).ischeck;
	}

	public int isreferenced(String fldname) {
		return info.get(fldname).isreferenced;
	}

	public String rktblname(String fldname) {
		return info.get(fldname).rktblname;
	}

	public String rkfldname(String fldname) {
		return info.get(fldname).rkfldname;
	}

	public String fkeytblname(String fldname) {
		return info.get(fldname).fkeytblname;
	}

	public String fkeyfldname(String fldname) {
		return info.get(fldname).fkeyfldname;
	}

	public String termstring(String fldname) {
		return info.get(fldname).termstring;
	}

	public List<String> getKeyset() {
		List<String> keyset = new ArrayList<String>();
		for (String s : fields()) {
			if (info.get(s).iskey == TRUE) {
				keyset.add(s);
			}
		}
		return keyset;
	}

	public List<String> getNotNullset() {
		List<String> notnullset = new ArrayList<String>();
		for (String s : fields()) {
			if (info.get(s).notnull == TRUE) {
				notnullset.add(s);
			}
		}
		return notnullset;
	}

	public List<String> getFKeyset() {
		List<String> fkeyset = new ArrayList<String>();
		for (String s : fields()) {
			if (info.get(s).fkey == TRUE) {
				fkeyset.add(s);
			}
		}
		return fkeyset;
	}
	
	public List<String> getRefset(){
		List<String> refset = new ArrayList<String>();
		for(String s: fields())
			if(info.get(s).isreferenced == TRUE)
				refset.add(s);
//		System.out.println("@@refset in schema:"+refset);
		return refset;
	}

	public List<String> getCheckset() {
		List<String> checkset = new ArrayList<String>();
		for (String s : fields()) {
			if (info.get(s).ischeck == TRUE)
				checkset.add(s);
		}
		return checkset;
	}

	public void setReferenced(String fldname, String rktblname, String rkfldname) {
		info.get(fldname).setReferenced(rktblname, rkfldname);
	}

	// public void setIsKey(String fldname) {
	// // if(hasField(fldname))
	// info.get(fldname).setIsKey();
	// }
	//
	// public void setIsNull(String fldname) {
	// // if(hasField(fldname))
	// info.get(fldname).setIsNull();
	// }

	class FieldInfo {
		int type, length, iskey, notnull, fkey, ischeck, isreferenced;
		String fkeytblname, fkeyfldname, termstring, rktblname, rkfldname;

		public FieldInfo(int t, int l, int k, int n, int f, int c, String ft,
				String ff, String ts, int ir, String rb, String rf) {
			this.type = t;
			this.length = l;
			this.iskey = k;
			this.notnull = n;
			this.fkey = f;
			this.ischeck = c;
			this.fkeytblname = ft;
			this.fkeyfldname = ff;
			this.termstring = ts;
			this.isreferenced = ir;
			this.rktblname = rb;
			this.rkfldname = rf;
		}

		public void setReferenced(String rktblname, String rkfldname) {
			this.isreferenced = TRUE;
			this.rktblname = rktblname;
			this.rkfldname = rkfldname;
		}
		//
		// public void setIsKey() {
		// this.iskey = TRUE;
		// }
		//
		// public void setIsNull() {
		// this.notnull = TRUE;
		// }
	}

}
